टोकन बकेट एल्गोरिथम का उपयोग करके एपीआई रेट लिमिटिंग के लिए एक व्यापक गाइड, जिसमें कार्यान्वयन विवरण और वैश्विक अनुप्रयोगों पर विचार शामिल हैं।
एपीआई रेट लिमिटिंग: टोकन बकेट एल्गोरिथम को लागू करना
आज की इंटरकनेक्टेड दुनिया में, एपीआई (एप्लिकेशन प्रोग्रामिंग इंटरफेस) अनगिनत एप्लिकेशन और सेवाओं की रीढ़ हैं। वे विभिन्न सॉफ्टवेयर सिस्टम को सहजता से संवाद करने और डेटा का आदान-प्रदान करने में सक्षम बनाते हैं। हालांकि, एपीआई की लोकप्रियता और पहुंच उन्हें संभावित दुरुपयोग और ओवरलोड के प्रति भी उजागर करती है। उचित सुरक्षा उपायों के बिना, एपीआई डिनायल-ऑफ-सर्विस (DoS) हमलों, संसाधन की कमी और समग्र प्रदर्शन में गिरावट के प्रति संवेदनशील हो सकते हैं। यहीं पर एपीआई रेट लिमिटिंग की भूमिका आती है।
रेट लिमिटिंग एपीआई की सुरक्षा के लिए एक महत्वपूर्ण तकनीक है जो एक क्लाइंट द्वारा एक विशिष्ट समय अवधि में किए जा सकने वाले अनुरोधों की संख्या को नियंत्रित करती है। यह उचित उपयोग सुनिश्चित करने, दुरुपयोग को रोकने और सभी उपयोगकर्ताओं के लिए एपीआई की स्थिरता और उपलब्धता बनाए रखने में मदद करती है। रेट लिमिटिंग को लागू करने के लिए विभिन्न एल्गोरिथम मौजूद हैं, और सबसे लोकप्रिय और प्रभावी में से एक टोकन बकेट एल्गोरिथम है।
टोकन बकेट एल्गोरिथम क्या है?
टोकन बकेट एल्गोरिथम रेट लिमिटिंग के लिए एक वैचारिक रूप से सरल लेकिन शक्तिशाली एल्गोरिथम है। एक ऐसी बकेट की कल्पना करें जिसमें एक निश्चित संख्या में टोकन रखे जा सकते हैं। टोकन एक पूर्वनिर्धारित दर पर बकेट में जोड़े जाते हैं। प्रत्येक आने वाला एपीआई अनुरोध बकेट से एक टोकन का उपभोग करता है। यदि बकेट में पर्याप्त टोकन हैं, तो अनुरोध को आगे बढ़ने की अनुमति दी जाती है। यदि बकेट खाली है (यानी, कोई टोकन उपलब्ध नहीं है), तो अनुरोध को या तो अस्वीकार कर दिया जाता है या तब तक कतार में रखा जाता है जब तक कि कोई टोकन उपलब्ध न हो जाए।
यहाँ प्रमुख घटकों का विवरण दिया गया है:
- बकेट का आकार (क्षमता): बकेट में रखे जा सकने वाले टोकन की अधिकतम संख्या। यह बर्स्ट क्षमता का प्रतिनिधित्व करता है – यानी अनुरोधों के अचानक आए उछाल को संभालने की क्षमता।
- टोकन रिफिल दर: वह दर जिस पर टोकन बकेट में जोड़े जाते हैं, जिसे आमतौर पर टोकन प्रति सेकंड या टोकन प्रति मिनट में मापा जाता है। यह औसत रेट लिमिट को परिभाषित करता है।
- अनुरोध: एक आने वाला एपीआई अनुरोध।
यह कैसे काम करता है:
- जब कोई अनुरोध आता है, तो एल्गोरिथम जांचता है कि बकेट में कोई टोकन हैं या नहीं।
- यदि बकेट में कम से कम एक टोकन है, तो एल्गोरिथम एक टोकन हटा देता है और अनुरोध को आगे बढ़ने की अनुमति देता है।
- यदि बकेट खाली है, तो एल्गोरिथम अनुरोध को अस्वीकार कर देता है या कतार में लगा देता है।
- टोकन बकेट की अधिकतम क्षमता तक, पूर्वनिर्धारित रिफिल दर पर बकेट में जोड़े जाते हैं।
टोकन बकेट एल्गोरिथम क्यों चुनें?
टोकन बकेट एल्गोरिथम अन्य रेट लिमिटिंग तकनीकों, जैसे कि फिक्स्ड विंडो काउंटर या स्लाइडिंग विंडो काउंटर, पर कई फायदे प्रदान करता है:
- बर्स्ट क्षमता: यह बकेट के आकार तक अनुरोधों के बर्स्ट की अनुमति देता है, जो उन वैध उपयोग पैटर्न को समायोजित करता है जिनमें कभी-कभी ट्रैफिक में स्पाइक्स शामिल हो सकते हैं।
- सुचारू रेट लिमिटिंग: रिफिल दर यह सुनिश्चित करती है कि औसत अनुरोध दर परिभाषित सीमाओं के भीतर रहे, जिससे निरंतर ओवरलोड को रोका जा सके।
- कॉन्फ़िगर करने की क्षमता: विभिन्न एपीआई या उपयोगकर्ता स्तरों के लिए रेट लिमिटिंग व्यवहार को ठीक करने के लिए बकेट के आकार और रिफिल दर को आसानी से समायोजित किया जा सकता है।
- सरलता: एल्गोरिथम को समझना और लागू करना अपेक्षाकृत सरल है, जो इसे कई परिदृश्यों के लिए एक व्यावहारिक विकल्प बनाता है।
- लचीलापन: इसे आईपी पते, उपयोगकर्ता आईडी, एपीआई कुंजी, या अन्य मानदंडों के आधार पर रेट लिमिटिंग सहित विभिन्न उपयोग के मामलों के लिए अनुकूलित किया जा सकता है।
कार्यान्वयन विवरण
टोकन बकेट एल्गोरिथम को लागू करने में बकेट की स्थिति (वर्तमान टोकन गणना और अंतिम अपडेटेड टाइमस्टैम्प) का प्रबंधन करना और आने वाले अनुरोधों को संभालने के लिए तर्क लागू करना शामिल है। यहाँ कार्यान्वयन के चरणों की एक वैचारिक रूपरेखा दी गई है:
- आरंभीकरण (Initialization):
- बकेट का प्रतिनिधित्व करने के लिए एक डेटा संरचना बनाएं, जिसमें आमतौर पर शामिल होता है:
- `tokens`: बकेट में टोकन की वर्तमान संख्या (बकेट के आकार के लिए आरंभ की गई)।
- `last_refill`: वह टाइमस्टैम्प जब बकेट को आखिरी बार रिफिल किया गया था।
- `bucket_size`: बकेट में रखे जा सकने वाले टोकन की अधिकतम संख्या।
- `refill_rate`: वह दर जिस पर टोकन बकेट में जोड़े जाते हैं (जैसे, टोकन प्रति सेकंड)।
- अनुरोध हैंडलिंग:
- जब कोई अनुरोध आता है, तो क्लाइंट के लिए बकेट प्राप्त करें (जैसे, आईपी पते या एपीआई कुंजी के आधार पर)। यदि बकेट मौजूद नहीं है, तो एक नया बनाएं।
- अंतिम रिफिल के बाद से बकेट में जोड़े जाने वाले टोकन की संख्या की गणना करें:
- `time_elapsed = current_time - last_refill`
- `tokens_to_add = time_elapsed * refill_rate`
- बकेट को अपडेट करें:
- `tokens = min(bucket_size, tokens + tokens_to_add)` (यह सुनिश्चित करें कि टोकन गणना बकेट के आकार से अधिक न हो)
- `last_refill = current_time`
- जांचें कि क्या अनुरोध को पूरा करने के लिए बकेट में पर्याप्त टोकन हैं:
- यदि `tokens >= 1`:
- टोकन गणना घटाएं: `tokens = tokens - 1`
- अनुरोध को आगे बढ़ने दें।
- अन्यथा (यदि `tokens < 1`):
- अनुरोध को अस्वीकार करें या कतार में लगाएं।
- रेट लिमिट पार हो जाने की त्रुटि लौटाएं (जैसे, HTTP स्थिति कोड 429 Too Many Requests)।
- अद्यतन बकेट स्थिति को बनाए रखें (जैसे, डेटाबेस या कैश में)।
उदाहरण कार्यान्वयन (वैचारिक)
यहाँ मुख्य चरणों को स्पष्ट करने के लिए एक सरलीकृत, वैचारिक उदाहरण (भाषा-विशिष्ट नहीं) दिया गया है:
class TokenBucket:
def __init__(self, bucket_size, refill_rate):
self.bucket_size = bucket_size
self.refill_rate = refill_rate # टोकन प्रति सेकंड
self.tokens = bucket_size
self.last_refill = time.time()
def consume(self, tokens_to_consume=1):
self._refill()
if self.tokens >= tokens_to_consume:
self.tokens -= tokens_to_consume
return True # अनुरोध की अनुमति है
else:
return False # अनुरोध अस्वीकृत (रेट लिमिट पार हो गई)
def _refill(self):
now = time.time()
time_elapsed = now - self.last_refill
tokens_to_add = time_elapsed * self.refill_rate
self.tokens = min(self.bucket_size, self.tokens + tokens_to_add)
self.last_refill = now
# उदाहरण उपयोग:
bucket = TokenBucket(bucket_size=10, refill_rate=2) # 10 का बकेट, 2 टोकन प्रति सेकंड की दर से रिफिल होता है
if bucket.consume():
# अनुरोध को संसाधित करें
print("अनुरोध की अनुमति है")
else:
# रेट लिमिट पार हो गई
print("रेट लिमिट पार हो गई")
ध्यान दें: यह एक बुनियादी उदाहरण है। एक प्रोडक्शन-रेडी कार्यान्वयन के लिए समवर्तीता (concurrency), दृढ़ता (persistence), और त्रुटि प्रबंधन (error handling) को संभालने की आवश्यकता होगी।
सही पैरामीटर चुनना: बकेट का आकार और रिफिल दर
प्रभावी रेट लिमिटिंग के लिए बकेट के आकार और रिफिल दर के लिए उपयुक्त मान चुनना महत्वपूर्ण है। इष्टतम मान विशिष्ट एपीआई, उसके इच्छित उपयोग के मामलों और सुरक्षा के वांछित स्तर पर निर्भर करते हैं।
- बकेट का आकार: एक बड़ा बकेट आकार अधिक बर्स्ट क्षमता की अनुमति देता है। यह उन एपीआई के लिए फायदेमंद हो सकता है जो कभी-कभी ट्रैफिक में स्पाइक्स का अनुभव करते हैं या जहां उपयोगकर्ताओं को वैध रूप से तेजी से अनुरोधों की एक श्रृंखला बनाने की आवश्यकता होती है। हालांकि, एक बहुत बड़ा बकेट आकार उच्च-मात्रा वाले उपयोग की लंबी अवधि की अनुमति देकर रेट लिमिटिंग के उद्देश्य को विफल कर सकता है। बकेट का आकार निर्धारित करते समय अपने उपयोगकर्ताओं के विशिष्ट बर्स्ट पैटर्न पर विचार करें। उदाहरण के लिए, एक फोटो संपादन एपीआई को उपयोगकर्ताओं को छवियों के एक बैच को जल्दी से अपलोड करने की अनुमति देने के लिए एक बड़े बकेट की आवश्यकता हो सकती है।
- रिफिल दर: रिफिल दर औसत अनुरोध दर निर्धारित करती है जिसकी अनुमति है। एक उच्च रिफिल दर प्रति यूनिट समय में अधिक अनुरोधों की अनुमति देती है, जबकि एक कम रिफिल दर अधिक प्रतिबंधात्मक होती है। रिफिल दर को एपीआई की क्षमता और उपयोगकर्ताओं के बीच निष्पक्षता के वांछित स्तर के आधार पर चुना जाना चाहिए। यदि आपका एपीआई संसाधन-गहन है, तो आप एक कम रिफिल दर चाहेंगे। विभिन्न उपयोगकर्ता स्तरों पर भी विचार करें; प्रीमियम उपयोगकर्ताओं को मुफ्त उपयोगकर्ताओं की तुलना में उच्च रिफिल दर मिल सकती है।
उदाहरण परिदृश्य:
- सोशल मीडिया प्लेटफॉर्म के लिए सार्वजनिक एपीआई: दुरुपयोग को रोकने और सभी उपयोगकर्ताओं के लिए उचित पहुंच सुनिश्चित करने के लिए एक छोटा बकेट आकार (जैसे, 10-20 अनुरोध) और एक मध्यम रिफिल दर (जैसे, 2-5 अनुरोध प्रति सेकंड) उपयुक्त हो सकती है।
- माइक्रोसेवाइस संचार के लिए आंतरिक एपीआई: एक बड़ा बकेट आकार (जैसे, 50-100 अनुरोध) और एक उच्च रिफिल दर (जैसे, 10-20 अनुरोध प्रति सेकंड) उपयुक्त हो सकता है, यह मानते हुए कि आंतरिक नेटवर्क अपेक्षाकृत विश्वसनीय है और माइक्रोसेवाइस में पर्याप्त क्षमता है।
- पेमेंट गेटवे के लिए एपीआई: धोखाधड़ी से बचाने और अनधिकृत लेनदेन को रोकने के लिए एक छोटा बकेट आकार (जैसे, 5-10 अनुरोध) और एक कम रिफिल दर (जैसे, 1-2 अनुरोध प्रति सेकंड) महत्वपूर्ण हैं।
पुनरावृत्तीय दृष्टिकोण: बकेट के आकार और रिफिल दर के लिए उचित प्रारंभिक मानों के साथ शुरुआत करें, और फिर एपीआई के प्रदर्शन और उपयोग पैटर्न की निगरानी करें। वास्तविक दुनिया के डेटा और फीडबैक के आधार पर आवश्यकतानुसार मापदंडों को समायोजित करें।
बकेट की स्थिति को संग्रहीत करना
टोकन बकेट एल्गोरिथम को प्रत्येक बकेट की स्थिति (टोकन गणना और अंतिम रिफिल टाइमस्टैम्प) को स्थायी रूप से संग्रहीत करने की आवश्यकता होती है। प्रदर्शन और स्केलेबिलिटी के लिए सही भंडारण तंत्र चुनना महत्वपूर्ण है।
सामान्य भंडारण विकल्प:
- इन-मेमोरी कैश (जैसे, Redis, Memcached): सबसे तेज प्रदर्शन प्रदान करता है, क्योंकि डेटा मेमोरी में संग्रहीत होता है। उच्च-ट्रैफिक एपीआई के लिए उपयुक्त जहां कम विलंबता महत्वपूर्ण है। हालांकि, यदि कैश सर्वर पुनरारंभ होता है तो डेटा खो जाता है, इसलिए प्रतिकृति या दृढ़ता तंत्र का उपयोग करने पर विचार करें।
- रिलेशनल डेटाबेस (जैसे, PostgreSQL, MySQL): स्थायित्व और स्थिरता प्रदान करता है। उन एपीआई के लिए उपयुक्त जहां डेटा अखंडता सर्वोपरि है। हालांकि, डेटाबेस संचालन इन-मेमोरी कैश संचालन की तुलना में धीमा हो सकता है, इसलिए प्रश्नों को अनुकूलित करें और जहां संभव हो कैशिंग परतों का उपयोग करें।
- NoSQL डेटाबेस (जैसे, Cassandra, MongoDB): स्केलेबिलिटी और लचीलापन प्रदान करता है। बहुत अधिक अनुरोध मात्रा वाले एपीआई या जहां डेटा स्कीमा विकसित हो रहा है, के लिए उपयुक्त है।
विचारणीय बातें:
- प्रदर्शन: एक भंडारण तंत्र चुनें जो अपेक्षित पढ़ने और लिखने के भार को कम विलंबता के साथ संभाल सके।
- स्केलेबिलिटी: सुनिश्चित करें कि भंडारण तंत्र बढ़ते ट्रैफिक को समायोजित करने के लिए क्षैतिज रूप से स्केल कर सकता है।
- स्थायित्व: विभिन्न भंडारण विकल्पों के डेटा हानि के प्रभावों पर विचार करें।
- लागत: विभिन्न भंडारण समाधानों की लागत का मूल्यांकन करें।
रेट लिमिट पार होने की घटनाओं को संभालना
जब कोई क्लाइंट रेट लिमिट पार कर जाता है, तो घटना को शालीनता से संभालना और जानकारीपूर्ण फीडबैक प्रदान करना महत्वपूर्ण है।
सर्वोत्तम अभ्यास:
- HTTP स्थिति कोड: मानक HTTP स्थिति कोड 429 Too Many Requests लौटाएं।
- Retry-After हेडर: प्रतिक्रिया में `Retry-After` हेडर शामिल करें, जो यह बताता है कि क्लाइंट को दूसरा अनुरोध करने से पहले कितने सेकंड इंतजार करना चाहिए। यह क्लाइंट को बार-बार अनुरोधों के साथ एपीआई पर बोझ डालने से बचने में मदद करता है।
- जानकारीपूर्ण त्रुटि संदेश: एक स्पष्ट और संक्षिप्त त्रुटि संदेश प्रदान करें जो यह समझाए कि रेट लिमिट पार हो गई है और समस्या को हल करने का तरीका सुझाए (जैसे, पुनः प्रयास करने से पहले प्रतीक्षा करें)।
- लॉगिंग और मॉनिटरिंग: निगरानी और विश्लेषण के लिए रेट लिमिट पार होने की घटनाओं को लॉग करें। यह संभावित दुरुपयोग या गलत कॉन्फ़िगर किए गए क्लाइंट की पहचान करने में मदद कर सकता है।
उदाहरण प्रतिक्रिया:
HTTP/1.1 429 Too Many Requests
Content-Type: application/json
Retry-After: 60
{
"error": "रेट लिमिट पार हो गई है। कृपया पुनः प्रयास करने से पहले 60 सेकंड प्रतीक्षा करें।"
}
उन्नत विचार
बुनियादी कार्यान्वयन से परे, कई उन्नत विचार एपीआई रेट लिमिटिंग की प्रभावशीलता और लचीलेपन को और बढ़ा सकते हैं।
- स्तरीय रेट लिमिटिंग: विभिन्न उपयोगकर्ता स्तरों (जैसे, मुफ्त, बुनियादी, प्रीमियम) के लिए अलग-अलग रेट लिमिट लागू करें। यह आपको सदस्यता योजनाओं या अन्य मानदंडों के आधार पर सेवा के विभिन्न स्तरों की पेशकश करने की अनुमति देता है। सही रेट लिमिट लागू करने के लिए उपयोगकर्ता स्तर की जानकारी को बकेट के साथ संग्रहीत करें।
- गतिशील रेट लिमिटिंग: वास्तविक समय के सिस्टम लोड या अन्य कारकों के आधार पर रेट लिमिट को गतिशील रूप से समायोजित करें। उदाहरण के लिए, आप ओवरलोड को रोकने के लिए व्यस्त घंटों के दौरान रिफिल दर को कम कर सकते हैं। इसके लिए सिस्टम के प्रदर्शन की निगरानी करने और तदनुसार रेट लिमिट को समायोजित करने की आवश्यकता होती है।
- वितरित रेट लिमिटिंग: कई एपीआई सर्वर वाले वितरित वातावरण में, सभी सर्वरों पर सुसंगत रेट लिमिटिंग सुनिश्चित करने के लिए एक वितरित रेट लिमिटिंग समाधान लागू करें। बकेट को सर्वरों में वितरित करने के लिए एक साझा भंडारण तंत्र (जैसे, Redis क्लस्टर) और सुसंगत हैशिंग का उपयोग करें।
- दानेदार रेट लिमिटिंग: विभिन्न एपीआई एंडपॉइंट्स या संसाधनों को उनकी जटिलता और संसाधन खपत के आधार पर अलग-अलग रेट लिमिट करें। उदाहरण के लिए, एक साधारण केवल-पढ़ने वाले एंडपॉइंट की दर एक जटिल लिखने वाले ऑपरेशन की तुलना में अधिक हो सकती है।
- आईपी-आधारित रेट लिमिटिंग बनाम उपयोगकर्ता-आधारित रेट लिमिटिंग: आईपी पते पर आधारित रेट लिमिटिंग और उपयोगकर्ता आईडी या एपीआई कुंजी पर आधारित रेट लिमिटिंग के बीच के ट्रेडऑफ पर विचार करें। आईपी-आधारित रेट लिमिटिंग विशिष्ट स्रोतों से दुर्भावनापूर्ण ट्रैफिक को रोकने के लिए प्रभावी हो सकती है, लेकिन यह उन वैध उपयोगकर्ताओं को भी प्रभावित कर सकती है जो एक आईपी पता साझा करते हैं (जैसे, NAT गेटवे के पीछे के उपयोगकर्ता)। उपयोगकर्ता-आधारित रेट लिमिटिंग व्यक्तिगत उपयोगकर्ताओं के उपयोग पर अधिक सटीक नियंत्रण प्रदान करती है। दोनों का संयोजन इष्टतम हो सकता है।
- एपीआई गेटवे के साथ एकीकरण: कार्यान्वयन और प्रबंधन को सरल बनाने के लिए अपने एपीआई गेटवे (जैसे, Kong, Tyk, Apigee) की रेट लिमिटिंग क्षमताओं का लाभ उठाएं। एपीआई गेटवे अक्सर अंतर्निहित रेट लिमिटिंग सुविधाएँ प्रदान करते हैं और आपको एक केंद्रीकृत इंटरफ़ेस के माध्यम से रेट लिमिट कॉन्फ़िगर करने की अनुमति देते हैं।
रेट लिमिटिंग पर वैश्विक परिप्रेक्ष्य
वैश्विक दर्शकों के लिए एपीआई रेट लिमिटिंग डिजाइन और कार्यान्वित करते समय, निम्नलिखित पर विचार करें:
- समय क्षेत्र: रिफिल अंतराल सेट करते समय विभिन्न समय क्षेत्रों का ध्यान रखें। स्थिरता के लिए UTC टाइमस्टैम्प का उपयोग करने पर विचार करें।
- नेटवर्क विलंबता: विभिन्न क्षेत्रों में नेटवर्क विलंबता काफी भिन्न हो सकती है। दूरस्थ स्थानों में उपयोगकर्ताओं को अनजाने में दंडित करने से बचने के लिए रेट लिमिट सेट करते समय संभावित विलंबता को ध्यान में रखें।
- क्षेत्रीय विनियम: किसी भी क्षेत्रीय विनियम या अनुपालन आवश्यकताओं से अवगत रहें जो एपीआई उपयोग को प्रभावित कर सकती हैं। उदाहरण के लिए, कुछ क्षेत्रों में डेटा गोपनीयता कानून हो सकते हैं जो एकत्र या संसाधित किए जा सकने वाले डेटा की मात्रा को सीमित करते हैं।
- कंटेंट डिलीवरी नेटवर्क (CDNs): एपीआई सामग्री वितरित करने और विभिन्न क्षेत्रों में उपयोगकर्ताओं के लिए विलंबता को कम करने के लिए CDNs का उपयोग करें।
- भाषा और स्थानीयकरण: वैश्विक दर्शकों को पूरा करने के लिए कई भाषाओं में त्रुटि संदेश और दस्तावेज़ीकरण प्रदान करें।
निष्कर्ष
एपीआई रेट लिमिटिंग एपीआई को दुरुपयोग से बचाने और उनकी स्थिरता और उपलब्धता सुनिश्चित करने के लिए एक आवश्यक अभ्यास है। टोकन बकेट एल्गोरिथम विभिन्न परिदृश्यों में रेट लिमिटिंग को लागू करने के लिए एक लचीला और प्रभावी समाधान प्रदान करता है। बकेट के आकार और रिफिल दर को सावधानीपूर्वक चुनकर, बकेट की स्थिति को कुशलतापूर्वक संग्रहीत करके, और रेट लिमिट पार होने की घटनाओं को शालीनता से संभालकर, आप एक मजबूत और स्केलेबल रेट लिमिटिंग सिस्टम बना सकते हैं जो आपके एपीआई की सुरक्षा करता है और आपके वैश्विक दर्शकों के लिए एक सकारात्मक उपयोगकर्ता अनुभव प्रदान करता है। अपने एपीआई उपयोग की लगातार निगरानी करना और बदलते ट्रैफिक पैटर्न और सुरक्षा खतरों के अनुकूल होने के लिए आवश्यकतानुसार अपने रेट लिमिटिंग मापदंडों को समायोजित करना याद रखें।
टोकन बकेट एल्गोरिथम के सिद्धांतों और कार्यान्वयन विवरणों को समझकर, आप अपने एपीआई को प्रभावी ढंग से सुरक्षित कर सकते हैं और विश्वसनीय और स्केलेबल एप्लिकेशन बना सकते हैं जो दुनिया भर के उपयोगकर्ताओं की सेवा करते हैं।